
#include <stdio.h>
#include <string.h>
#include "../include/narray.h"
#include "../include/hash.h"
#include <malloc.h>
#include "../include/filedesc.h"
#include "../include/vfs.h"
#include "../include/bst.h"
#include "../include/vfs_errorcodes.h"
#include <unistd.h> 
char* label;

int max_fd; 
int current_fd_id; 
int no_of_fd;


char* create(char* label,int size)
 	{      
 	int nosblock;
	fd root_dir ;
	FILE *fdi ;
	char last_char =' ';
	int i;
	if(strlen(label)>30)
	{
		strcpy(error,"createvfs_FAILURE ");
		//strcat(error,"createvfs_failure");
	        strcat(error,ERR_VFS_CREATE_05);
	        
	        return error;
	}
	
	if(strpbrk (label,"/"))                       //checks if vfs name contains /
		{
		strcpy(error,"createvfs_FAILURE ");
	        strcat(error,ERR_VFS_CREATE_03);
	        
	        return error;
		} 
	if(size <1||size>1024)
	{
	          strcpy(error,"createvfs_FAILURE ");
	          strcat(error,ERR_VFS_CREATE_04);
	          
	          return error;
	}
	if( access( label, F_OK ) != -1 ) 
	{
		strcpy(error,"createvfs_FAILURE ");
	        strcat(error,ERR_VFS_CREATE_01);
	        
	        return error;
		
	}
	nosblock = ((size*1024) - 20)/(sizeof(fd) + BLOCK_SIZE + 4);
	//printf("%d ->is the block \n",nosblock);
	size_meta_header = sizeof(int)*5;
	size_of_header_1 = nosblock*sizeof(fd) ;
	size_of_header_2 =  nosblock *4;
	max_fd = nosblock; 
	current_fd_id = 1; 
	no_of_fd = 1 ;
	
	//initialize the root
	
	root_dir.is_dir =1;
	root_dir.fd_id = 1;
	root_dir.size = 0;
	strcpy(root_dir.file_name,"/");
	strcpy(root_dir.path,"/");
		
	if(( fdi = fopen(label,"wb+"))== NULL)
	{
		strcpy(error,"createvfs_FAILURE ");
	    	strcat(error,strcat(ERR_VFS_CREATE_02,">"));
	    	return error;
				
	}
         
	else
	{       
		fseek(fdi,size*1024, SEEK_SET);
		fwrite( &last_char, sizeof(char),1,fdi);
		//store the metaheader data
		fseek(fdi,0, SEEK_SET);
                fwrite( &no_of_fd, sizeof(int),1,fdi);
                fwrite( &max_fd, sizeof(int),1,fdi);
		fwrite( &size_of_header_1, sizeof(int),1,fdi);
		fwrite( &size_of_header_2, sizeof(int),1,fdi);
		fwrite( &size_meta_header, sizeof(int),1,fdi);
		fseek(fdi,size_meta_header , SEEK_SET);
		fwrite( &root_dir, sizeof(fd),1,fdi);
      /*for time being hard code it
                  f.is_dir =1;
                  f.fd_id = 2;
	          f.size = 10;
                  
	          strcpy(f.file_name,"home");
	          strcpy(f.path,"/");
		
		fwrite(&f,sizeof(fd),1,fdi);
                 
                  f1.is_dir =1;
                  f1.fd_id = 3;
	          f1.size = 10;
	          strcpy(f1.file_name,"abc");
	          strcpy(f1.path,"/home");
		
		fwrite(&f1,sizeof(fd),1,fdi);
                  f2.is_dir =1;
                  f2.fd_id = 3;
	          f2.size = 10;
	          strcpy(f2.file_name,"sdf");
	          strcpy(f2.path,"/home");
		  
		
		fwrite(&f2,sizeof(fd),1,fdi);*/
		
		// store the free list containg the list of all the block numbers
		//block number starting from 0
		fseek(fdi,size_meta_header + size_of_header_1, SEEK_SET);
		for(i=0; i< max_fd ; i++)                         
		{          int t=0;
			fwrite( &t, sizeof(int),1,fdi);
                        //printf("free or not:%d",t);
		}
		fclose(fdi);
	}
	strcpy(error,"createvfs_SUCCESS");
	//printf("%s\n",error);
	return error;
 }


char* mount(char *label)
  {     

	
        l_node *temp;
        int k,h,try;
        char fname[100] ,fpath[100];
	FILE *f;
	int j;
	fd *i;
	f=fopen(label,"rb+");
if(f==NULL){
		strcpy(error,"mountvfs_FAILURE ");
	    	strcat(error,ERR_VFS_MOUNT_02);
	    	
	    	//printf("%s\n",error);
	    	return error;
	    	}
	

        if( access( label, F_OK ) == -1 ) 
	{
		
		strcpy(error,"mountvfs_FAILURE ");
	        strcat(error,ERR_VFS_MOUNT_01 );
	        //printf("%s\t%s\n",error,label);
	        return error;
		
	}
        if((strcmp(label,labels)==0)||strlen(labels)!=0)
 		{
 		strcpy(error,"mountvfs_FAILURE ");
	    	strcat(error,ERR_VFS_MOUNT_03);
	 	    	//printf("%s\n",error);
	    	return error;
		}	
        strcpy(labels,label); 
        bst_root=NULL;
        start=NULL;
	fread(&fdno,sizeof(int),1,f);
	fread(&maxfd,sizeof(int),1,f);
	fread(&size_of_header_1, sizeof(int),1,f);
	fread(&size_of_header_2, sizeof(int),1,f);
	fread(&size_meta_header, sizeof(int),1,f);
	//printf("fd no is %d\n",fdno);
	fseek(f,0,0);
	fseek(f,size_meta_header,SEEK_SET);
	for(j=0;j<fdno;j++)                              // go on reading all the file descriptors and populate the data structures
		{
                        
			i=(fd*)malloc(sizeof(fd));
			fread(i,sizeof(fd),1,f);
			k=insert_node(&root,i);
			//printf("%s\t%s\n",i->file_name,i->path);
 			strcpy(fname,i->file_name);
			strcpy(fpath,i->path); 
 			insert_into_list(fname,fpath);
 			int m=bst_insert ( &bst_root,i );
			//printf("%d is j\n",j);

		}
	fseek(f,size_meta_header + size_of_header_1, SEEK_SET);
	int ie=0,ke;
      // creation of free list
	//printf("%d size of fd\n",maxfd);
        
	while(ie<maxfd)
	{
  		fread(&ke,sizeof(int),1,f);
		l_node *newnode=(l_node *)malloc(sizeof(l_node));
		newnode->no=ie;
		newnode->value=ke;
                
		
		if(start==NULL){
	 		start=newnode;
	 		start->next=NULL;
	 		temp=start;
		}
		else
		{
  			while(temp->next!=NULL){
 				temp=temp->next;
			}
			newnode->next=NULL;
			temp->next=newnode;

		}
		
	ie++;
	
	}
        //printf("%d ifioe\n",start->no);
 

// freelist ends here
	fclose(f);
        //print_inorder(bst_root);
      // 	printtrees(root,fp);
        /*printf("************************************************************\n");
        display();
        printf("************************************************************\n");
        
        fclose(fp);*/
        
        strcpy(error,"mountvfs_SUCCESS ");
        //printf("%s\n",error);
        return error;
}







char* unmount(char *label){
	FILE *f;
	l_node *temp;
	temp=start;
	b_node *b;
	b=bst_root;
	int i;
	fd *j;
	f=fopen(label,"rb+");
	 if( access( label, F_OK ) == -1 ) 
	{
		strcpy(error,"unmountvfs_FAILURE ");
	        strcat(error,ERR_VFS_UNMOUNT_01);
	       
	        //printf("%s\n",error);
	        return error;
		
	}
        if((strcmp(label,labels)!=0)||strlen(labels)==0)
 		{
 		strcpy(error,"unmountvfs_FAILURE ");
	    	strcat(error,ERR_VFS_UNMOUNT_03);
	    	//printf("%s\n",error);
	    	return error;
	}
	if(f==NULL)
	{
		strcpy(error,"unmountvfs_FAILURE ");
	    	strcat(error,ERR_VFS_UNMOUNT_02);
	    	
	    	//printf("%s\n",error);
	    	return error;
	    	}
	
	        //printf("%d ois the fd\n",fdno);
		fwrite( &fdno, sizeof(int),1,f);
                fwrite( &maxfd, sizeof(int),1,f);
		fwrite( &size_of_header_1, sizeof(int),1,f);
		fwrite( &size_of_header_2, sizeof(int),1,f);
		fwrite( &size_meta_header, sizeof(int),1,f);
		fseek(f,0,0);
		fseek(f,size_meta_header,SEEK_SET);
		savetrees(root,f);
		fseek(f,0,0);
		fseek(f,size_meta_header+size_of_header_1,SEEK_SET);
		while(temp!=NULL)
		{
			fwrite(&temp->value,sizeof(int),1,f);
			temp=temp->next;
		}
		root=NULL;
		*hash_table=NULL;
		free(root);
		strcpy(labels,"\0");
		fclose(f);
		strcpy(error,"unmountvfs_SUCCESS");
		return error;
	}

void savetrees( t_node *root,FILE *f){
	int h;
	if(root!=NULL)
       {
               //t_node *temp=*root;
               if(root->is_deleted!=1)
               {
                     
                     fd *data;
                     data=root->data;
                     fwrite(data,sizeof(fd),1,f);
                     //h=hash(data->file_name);
                     //printf("\n%s\t\t %s\n",data->file_name,data->path);
                     deletion(data->file_name,data->path);
                     
                 if(root->left_child!=NULL)
                  {
                       savetrees(root->left_child,f);
                  }

                if(root->right_siblings!=NULL)
                  {
                       savetrees(root->right_siblings,f);
                  }
                }

          

         
     }

}


